#include "stdafx.h"
#include "psMatrix.h"


/**
 * Default-Constructor. Creates empty matrix.
 */
psMatrix::psMatrix() : m_pComp(NULL), m_rows(0), m_cols(0), m_ld(0)
{
	// NOTHING TO DO
}


/**
 * Destructor.
 */
psMatrix::~psMatrix()
{
	// Reset everything to zero, to leave memory absolute clean.
	if (m_pComp) {
		delete[] m_pComp;
		m_pComp = NULL;
	}

	m_rows = 0;
	m_cols = 0;
	m_ld = 0;
}


double psMatrix::getComp(const int row, const int col) const
{
	if ((row < m_rows) && (col < m_ld)) {
		return m_pComp[row + col*m_ld];
	} else {
		ASSERT(false); // can't get the component!
		return 0.0;
	}
}


/**
 * Returns the component pointer of the matrix.
 * @return	pointer to the components
 */
double* psMatrix::getCompPtr() const
{
	return m_pComp;
}


int psMatrix::getRowCount() const
{
	return m_rows;
}


int psMatrix::getColCount() const
{
	return m_cols;
}


int psMatrix::getLeadingDimension() const
{
	return m_ld;
}


bool psMatrix::isSquared() const
{
	return (m_rows == m_cols);
}


void psMatrix::print(const int digits /*= 4*/) const
{
	std::cout.precision(digits);
	std::cout.setf(std::ios::fixed, std::ios::floatfield);

	std::cout << "Printing " << m_rows << "x" << m_cols << "-matrix (with ld = " << m_ld << "):" << std::endl;

	double* pCurrComp = NULL;
	int col;
	for (int row = 0; row < m_ld; row++) {
		std::cout << row << ":";
		pCurrComp = m_pComp + row;

		for (col = 0; col < m_cols; col++) {
			std::cout << "\t" << *pCurrComp; // or m_pComp[row + col*m_ld]
			pCurrComp += m_ld;
		}
		std::cout << std::endl;
	}
}


/**
 * Sets the component of the matrix at (row, col), where row and col starts with 0 and must be
 * valid (within the previous setted size).
 * @param row		row of the component
 * @param	col		col of the component
 * @param	comp	the new value of the component
 */
void psMatrix::setComp(const int row, const int col, const double comp)
{
	if ((row < m_rows) && (col < m_ld)) {
		m_pComp[row + col*m_ld] = comp;
	} else {
		ASSERT(false); // can't set the component!
	}
}


void psMatrix::setSize(const int rows, const int cols)
{
	m_rows = rows;
	m_cols = cols;
	m_ld = rows;
	this->initNewSize();
}


void psMatrix::setSize(const int rows, const int cols, const int ld)
{
	m_rows = rows;
	m_cols = cols;
	ASSERT(rows <= ld);
	m_ld = ld;
	this->initNewSize();
}


void psMatrix::setSizeSqrd(const int dim)
{
	m_rows = dim;
	m_cols = dim;
	m_ld = dim;
	this->initNewSize();
}


void psMatrix::setSizeSqrd(const int dim, const int ld)
{
	m_rows = dim;
	m_cols = dim;
	ASSERT(dim <= ld);
	m_ld = ld;
	this->initNewSize();
}


/**
 * Initializes the components inclusive leading dimensions with numbers from 1 to count of
 * components (cols first!).
 */
void psMatrix::setToIntIntervalInclLd()
{
	double* pCurrComp = m_pComp;
	int compCount = m_cols * m_ld;
	int val = 1;
	while (val <= compCount) {
		*pCurrComp = (double)val;
		pCurrComp++;
		val++;
	}
}


/**
 * Initializes the components inclusive leading dimensions with random numbers between 0 and 1.
 */
void psMatrix::setToRandomInclLd()
{
	// Zufallszahlen-Generator initialisieren (nur 1x!)
	static bool bInitialized = false;
	if (!bInitialized) {
		srand(time(NULL));
		bInitialized = true;
	}


	double* pCurrComp = m_pComp;
	int compCount = m_cols * m_ld;
	int i = 1;
	while (i <= compCount) {
		*pCurrComp = (double)rand() / RAND_MAX;
		pCurrComp++;
		i++;
	}
}


void psMatrix::setToZero()
{
	double* pCurrComp = m_pComp;
	int compCount = m_cols * m_ld;
	int i = 1;
	while (i <= compCount) {
		*pCurrComp = 0.0;
		pCurrComp++;
		i++;
	}
}



/**************************************************************************************************
 *     protected member functions                                                                 *
 **************************************************************************************************/
void psMatrix::initNewSize()
{
	// first tidy up
	if (m_pComp) {
		delete[] m_pComp;
		m_pComp = NULL;
	}

	// try to create new one
	if (m_rows <= m_ld) {
		if ((m_rows > 0) && (m_cols > 0)) {
			m_pComp = new double[m_cols * m_ld];
			ASSERT(m_pComp); // couldn't create array!
		} else {
			ASSERT(false); // empty matrix (0xn or mx0)!
		}
	} else {
		ASSERT(false); // ld too small!
	}
}